home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / package_16-january-2001.zip / Effects / cheapo fixer pro.cpp < prev    next >
C/C++ Source or Header  |  2000-10-14  |  8KB  |  355 lines

  1. // Copyright (C) Mikko Apo (apo@iki.fi)
  2. // The following code may be used to write free software
  3. // if credit is given to the original author.
  4. // Using it for anything else is not allowed without permission
  5. // from the author.
  6.  
  7. /*
  8.  
  9.   Random number generator from Oskari Tammelin's Noise.cpp Noise generator
  10.   FSM did the logarithmic volume slider mathematic formula
  11.  
  12. */
  13.  
  14. /*
  15. Revision history:
  16.   1.0    First release.
  17.   */
  18.  
  19. #include <stdlib.h>
  20. #include <time.h>
  21. #include <math.h>
  22. #include <string.h>
  23. #include "../mdk.h"
  24.  
  25. #define miCOMMAND_STRING "About..."
  26. #define miMACHINE_NAME "cheapo fixer pro"
  27. #define miSHORT_NAME "ch.fixer"
  28. #define miMACHINE_AUTHOR "Mikko Apo (apo@iki.fi)"
  29. #define miMAX_TRACKS        0
  30. #define miMIN_TRACKS        0
  31. #define miNUMGLOBALPARAMETERS 3
  32. #define miNUMTRACKPARAMETERS 0
  33. #define miNUMATTRIBUTES 0
  34. #define miVERSION "1.0"
  35.  
  36. //    Parameters
  37.  
  38. CMachineParameter const paraThreshold = 
  39. { pt_word, "Threshold","Threshold [0 - 32768]",0,32768,0xffff,MPF_STATE,0 };
  40.  
  41. CMachineParameter const paraLevel = 
  42. { pt_byte, "Noise Level","Whitenoise Level",0,0x7f,0xff,MPF_STATE,0x20 };
  43.  
  44. // 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, infinite
  45.  
  46. CMachineParameter const paraZombie = 
  47. { pt_byte, "Re-animate","Ticks to keep the signal chain on.",0,13,0xff,MPF_STATE,6};
  48.  
  49.  
  50. // List of all parameters, track parameters last
  51.  
  52. CMachineParameter const *pParameters[] = 
  53. { ¶Threshold,¶Level, ¶Zombie};
  54.  
  55. #pragma pack(1)
  56.  
  57. class gvals
  58. {
  59. public:
  60.     word threshold;
  61.     byte level;
  62.     byte zombie;
  63. };
  64.  
  65. #pragma pack()
  66.  
  67. // Machine's info
  68.  
  69. CMachineInfo const MacInfo = 
  70. {
  71.     MT_EFFECT,MI_VERSION,MIF_DOES_INPUT_MIXING,miMIN_TRACKS,miMAX_TRACKS,
  72.     miNUMGLOBALPARAMETERS,miNUMTRACKPARAMETERS,pParameters,miNUMATTRIBUTES,NULL,
  73. #ifdef _DEBUG
  74.     miMACHINE_NAME" [DEBUG]"
  75. #else
  76.     miMACHINE_NAME
  77. #endif
  78.     ,miSHORT_NAME,miMACHINE_AUTHOR,miCOMMAND_STRING
  79. };
  80.  
  81.  
  82. class miex : public CMDKMachineInterfaceEx
  83. {
  84.  
  85. };
  86.  
  87. class mi : public CMDKMachineInterface
  88. {
  89. public:
  90.     mi();
  91.  
  92.     virtual void Command(int const i);
  93.     virtual void Tick();
  94.     virtual char const *DescribeValue(int const param, int const value);
  95.  
  96.     virtual void MDKInit(CMachineDataInput * const pi);
  97.     virtual bool MDKWork(float *psamples, int numsamples, int const mode);
  98.     virtual bool MDKWorkStereo(float *psamples, int numsamples, int const mode);
  99.     virtual void MDKSave(CMachineDataOutput * const po) { }
  100.  
  101.     public:
  102.     virtual CMDKMachineInterfaceEx *GetEx() { return &ex; }
  103.     virtual void OutputModeChanged(bool stereo) {};
  104.  
  105.     public:
  106.     miex ex;
  107.     gvals gval;
  108.  
  109. private:
  110.  
  111.     float valThreshold;
  112.     int RandStat;
  113.     float amp;
  114.     int valLevel;
  115.     long valZombie;
  116.     bool alive;
  117.     long zombiecounter;
  118. };
  119.  
  120.  
  121. DLL_EXPORTS
  122.  
  123. mi::mi()
  124. {
  125.     GlobalVals = &gval;
  126. }
  127.  
  128. void mi::Command(int const i)
  129. {
  130.     static char txt[500];
  131.     switch(i)
  132.     {
  133.     case 0:
  134.         pCB->MessageBox(miMACHINE_NAME"\n\nBuild date: "__DATE__"\nVersion: "miVERSION"\nCoded by: "miMACHINE_AUTHOR"\nThanks to Oskari and FSM for code snippets.\n\nCheck out http://www.iki.fi/apo/buzz/\nfor more buzz stuff.\n\nExcellent skin made by Hymax.");
  135.         break;
  136.  
  137.     }
  138. }
  139.  
  140. char const *mi::DescribeValue(int const param, int const value)
  141. {
  142.     static char txt[100];
  143.  
  144.     switch(param)
  145.     {
  146.     case 0:
  147.         if(value)
  148.         {
  149.           sprintf(txt,"%d",value);
  150.         } else
  151.         {
  152.             return("0.1");
  153.         }
  154.         break;
  155.     case 1:
  156.             sprintf(txt,"%.2fdB",20*(log10((((valThreshold)?valThreshold:0.1)*pow(2.0,(1-value/127.0)*(-16))/32768))));
  157.         break;
  158.     case 2:
  159. // 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, infinite
  160.         switch(value)
  161.         {
  162.         case 0: return("off");
  163.         case 1:    return("1 tick");
  164.         case 2:    return("2 ticks");
  165.         case 3:    return("4 ticks");
  166.         case 4:    return("8 ticks");
  167.         case 5:    return("16 ticks");
  168.         case 6:    return("32 ticks");
  169.         case 7:    return("64 ticks");
  170.         case 8:    return("128 ticks");
  171.         case 9: return("256 ticks");
  172.         case 10: return("512 ticks");
  173.         case 11: return("1024 ticks");
  174.         case 12: return("infinitely");
  175.         case 13: return("wake up");
  176.         }
  177.         break;
  178.     }
  179.     return txt;
  180. }
  181.  
  182. void mi::MDKInit(CMachineDataInput * const pi)
  183. {
  184.     valThreshold = (float)paraThreshold.DefValue;
  185.     zombiecounter=valZombie = 32*pMasterInfo->SamplesPerTick;
  186.     alive=false;
  187.     valLevel = paraLevel.DefValue;
  188.     RandStat = 0x16BA2118;    // initialize random generator
  189.     amp=(float)((pow(2.0,(1-valLevel/127.0)*(-16))*valThreshold)/0x7fff);
  190. }
  191.  
  192. void mi::Tick()
  193. {
  194.     if (gval.zombie != paraZombie.NoValue)
  195.     {
  196.         long tmp;
  197. // 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, infinite
  198.         switch(gval.zombie)
  199.         {
  200.         case 0:tmp=0;break;
  201.         case 1:tmp=1;break;
  202.         case 2:tmp=2;break;
  203.         case 3:tmp=4;break;
  204.         case 4:tmp=8;break;
  205.         case 5:tmp=16;break;
  206.         case 6:tmp=32;break;
  207.         case 7:tmp=64;break;
  208.         case 8:tmp=128;break;
  209.         case 9:tmp=256;break;
  210.         case 10:tmp=512;break;
  211.         case 11:tmp=1024;break;
  212.         case 12:
  213.             zombiecounter=valZombie=0x3fffffff;
  214.             break;
  215.         case 13:
  216.             alive=true;
  217.             zombiecounter=valZombie;
  218.             break;
  219.         }
  220.         if(gval.zombie<12)
  221.         {
  222.             tmp*=pMasterInfo->SamplesPerTick;
  223.             zombiecounter+=tmp-valZombie;
  224.             if(zombiecounter<0)
  225.             {
  226.  // we've been keeping the signal up, but the new timeout is shorter
  227.                 alive=false;
  228.             }
  229.             valZombie=tmp;
  230.         }
  231.     }
  232.  
  233.     bool changed=false;
  234.     if (gval.threshold != paraThreshold.NoValue)
  235.     {
  236.         valThreshold=gval.threshold;
  237.         changed=true;
  238.     }
  239.     if (gval.level != paraLevel.NoValue)
  240.     {
  241.         valLevel=gval.level;
  242.         changed=true;
  243.     }
  244.     if(changed)
  245.     {
  246.     if(valThreshold)
  247.     {
  248.         amp = (float) ((pow(2.0,(1-valLevel/127.0)*(-16))*valThreshold)/0x7fff);
  249.     } else
  250.     {
  251.         amp = (float) ((pow(2.0,(1-valLevel/127.0)*(-16))*0.1)/0x7fff);
  252.     }
  253.     }
  254.  
  255.  
  256. bool mi::MDKWork(float *psamples, int numsamples, int const mode)
  257. {
  258.     if (mode==WM_NOIO)
  259.     {
  260.         return false;
  261.     }
  262.  
  263.     if (mode == WM_READ)        // <thru>
  264.         return true;
  265.  
  266.     if(mode==WM_WRITE)
  267.     {
  268.         if(alive) // wake up the dead signal
  269.         {
  270.             zombiecounter-=numsamples;
  271.             do 
  272.             {
  273.                 RandStat = ((RandStat * 1103515245 + 12345) & 0xffff) - 0x8000;
  274.                 *psamples= amp*RandStat;
  275.                 psamples++;
  276.             } while(--numsamples);
  277.             if(zombiecounter<0) // we don't loop next time
  278.             {
  279.                 alive=false;
  280.             }
  281.             return (true); // we messed with the signal
  282.         }
  283.         return false; // we didn't do anything to the signal
  284.     }
  285.  
  286.     alive=true;
  287.     zombiecounter=valZombie;
  288.     do 
  289.     {
  290.         if(fabs(*psamples)<=valThreshold)
  291.         {
  292.             RandStat = ((RandStat * 1103515245 + 12345) & 0xffff) - 0x8000;
  293.             *psamples= amp*RandStat;
  294.         }
  295.         psamples++;
  296.     } while(--numsamples);
  297.  
  298.     return true;
  299. }
  300.  
  301. bool mi::MDKWorkStereo(float *psamples, int numsamples, int const mode)
  302. {
  303.     if (mode==WM_NOIO)
  304.     {
  305.         return false;
  306.     }
  307.  
  308.     if (mode == WM_READ)        // <thru>
  309.         return true;
  310.  
  311.     if(mode==WM_WRITE)
  312.     {
  313.         if(alive) // wake up the dead signal
  314.         {
  315.             zombiecounter-=numsamples;
  316.             do 
  317.             {
  318.                 RandStat = ((RandStat * 1103515245 + 12345) & 0xffff) - 0x8000;
  319.                 psamples[0]= amp*RandStat;
  320.                 RandStat = ((RandStat * 1103515245 + 12345) & 0xffff) - 0x8000;
  321.                 psamples[1]= amp*RandStat;
  322.                 psamples+=2;
  323.             } while(--numsamples);
  324.             if(zombiecounter<0) // we don't loop next time
  325.             {
  326.                 alive=false;
  327.             }
  328.             return (true); // we messed with the signal
  329.         }
  330.         return false; // we didn't do anything to the signal
  331.     }
  332.  
  333.     alive=true;
  334.     zombiecounter=valZombie;
  335.     do 
  336.     {
  337.         if(fabs(*psamples)<=valThreshold)
  338.         {
  339.             RandStat = ((RandStat * 1103515245 + 12345) & 0xffff) - 0x8000;
  340.             *psamples= amp*RandStat;
  341.         }
  342.         psamples++;
  343.         if(fabs(*psamples)<=valThreshold)
  344.         {
  345.             RandStat = ((RandStat * 1103515245 + 12345) & 0xffff) - 0x8000;
  346.             *psamples= amp*RandStat;
  347.         }
  348.         psamples++;
  349.     } while(--numsamples);
  350.  
  351.     return true;
  352. }
  353.  
  354.